﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace igflow.Components
{
        class igCamera : igComponent
        {
            public Vector3 DesiredTargetPosition;
            public Vector3 DesiredPosition;
            public Vector3 TargetPosition;
            public Vector3 DesiredFocusOffset;
            public Vector3 FocusOffset;
            bool cut = false;
            Matrix _view, _projection;
            public Matrix View
            {
                get
                {   
                    // update the view matrix
                    _view = Matrix.CreateLookAt(gameObject.Position, TargetPosition + FocusOffset, Vector3.Up);
                    return _view; 
                }
            }

            public Matrix Projection
            {
                get {
                    if (!isOrthographic)
                    {
                        _projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, aspect, near, far);
                    }
                    else
                    {
                        _projection = Matrix.CreateOrthographicOffCenter(0, Game1.screenWidth, Game1.screenHeight,0, near, far);
                    } 
                    return _projection;
                }
            }
            public float aspect;
            public float FOV;
            public float near;
            public float far;
            public bool isOrthographic;

            public override void Init()
            {
                TargetPosition = Vector3.Zero;
                DesiredFocusOffset = Vector3.Zero;
                DesiredTargetPosition = TargetPosition;
                DesiredPosition = gameObject.Position;
                base.Init();
            }

            float prop = 0.1f;
            float time = 0;
            public override void Update()
            {

                if (DesiredFocusOffset != FocusOffset)
                {
                    FocusOffset = Vector3.Lerp(FocusOffset, DesiredFocusOffset, prop);
                }
                if (DesiredPosition != gameObject.Position)
                {
                    gameObject.Position = Vector3.Lerp(gameObject.Position, DesiredPosition, prop);
                }
                if (DesiredTargetPosition != TargetPosition)
                {
                    TargetPosition = Vector3.Lerp(TargetPosition, DesiredTargetPosition, prop);
                }

                base.Update();
            } 

            public bool RayIntersects(GameObject.igGameObject gameObject, Ray ray)
            {
                // Check the gameObject actually has a collider
                /*
                gfCollider collider = (igComponent)gameObject.GetComponent(typeof(gfCollider));
                if (collider != null)
                {
                    Ray pickRay = ray;
                    float selectedDistance = float.MaxValue;
                    Nullable<float> result = pickRay.Intersects(collider.boundingSphere);
                    if (result.HasValue == true)
                    {
                        if (result.Value < selectedDistance)
                        {
                            return true;
                        }
                    }
                }
                 */
                return false;
            }
            public Ray GetCursorRay()
            {
                /*
                Vector3 nearsource = new Vector3(gfInputManager.Cursor.Position2D, 0f);
                Vector3 farsource = new Vector3(gfInputManager.Cursor.Position2D, 1f);

                Matrix world = Matrix.CreateTranslation(0, 0, 0);

                Vector3 nearPoint = GameRoot.Graphics.GraphicsDevice.Viewport.Unproject(nearsource,
                    GameRoot.mainCamera.Projection, GameRoot.mainCamera.View, world);

                Vector3 farPoint = GameRoot.Graphics.GraphicsDevice.Viewport.Unproject(farsource,
                    GameRoot.mainCamera.Projection, GameRoot.mainCamera.View, world);

                // Create a ray from the near clip plane to the far clip plane.
                Vector3 direction = farPoint - nearPoint;
                direction.Normalize();
                Ray pickRay = new Ray(nearPoint, direction);

                return pickRay;
            }

            // variables defined elsewhere

            // class that can access your ViewMatrix and ProjectionMatrix

            //----------------------------------------------------------------
            // GetPickedPosition() - gets 3D position of mouse pointer
            //                     - always on the the Y = 0 plane     
            //----------------------------------------------------------------
            public Vector3 GetPickedPosition(float x, float y)
            {
                // create 2 positions in screenspace using the cursor position. 0 is as
                // close as possible to the camera, 10 is as far away as possible
                Vector3 nearSource = new Vector3(x, y, 0f);
                Vector3 farSource = new Vector3(x, y, 0.5f); // was near clip

                // find the two screen space positions in world space
                Vector3 nearPoint = GameRoot.Graphics.GraphicsDevice.Viewport.Unproject(nearSource,
                                    GameRoot.mainCamera.Projection,
                                    GameRoot.mainCamera.View, Matrix.Identity);

                Vector3 farPoint = GameRoot.Graphics.GraphicsDevice.Viewport.Unproject(farSource,
                                    GameRoot.mainCamera.Projection,
                                    GameRoot.mainCamera.View, Matrix.Identity);

                // compute normalized direction vector from nearPoint to farPoint
                Vector3 direction = farPoint - nearPoint;
                direction.Normalize();

                // create a ray using nearPoint as the source
                Ray r = new Ray(nearPoint, direction);

                // calculate the ray-plane intersection point
                Vector3 n = new Vector3(0f, 0f, 1f);
                Plane p = new Plane(n, 0f);

                // calculate distance of intersection point from r.origin
                float denominator = Vector3.Dot(p.Normal, r.Direction);
                float numerator = Vector3.Dot(p.Normal, r.Position) + p.D;
                float t = -(numerator / denominator);

                // calculate the picked position on the y = 0 plane
                Vector3 pickedPosition = nearPoint + direction * t;
                return pickedPosition;
                */

                return new Ray();
            }
        }
}
